#include "noeud.h"

#include <string.h>

void noeud_create(Noeud** value, const char* element)
{
    (*value) = (Noeud*) malloc(sizeof(Noeud));
    noeud_initialize((*value),element);
}

void noeud_initialize(Noeud* value, const char* element)
{
    list_initialize(&value->successeurs,object_getArc(),0);
    list_initialize(&value->predecesseurs,object_getArc(),0);
    if(element != NULL)
    {
        value->element = (char*) malloc(sizeof(char) * (strlen(element) + 1));
        strcpy(value->element,element);
    }
    else
        value->element = NULL;
}

void noeud_destroy(Noeud** value)
{
    noeud_clear((*value));
    free((*value));
    (*value) = NULL;
}

void noeud_clear(Noeud* value)
{
    if(value != NULL)
    {
        list_clear(&value->successeurs);
        list_clear(&value->predecesseurs);
        if(value->element != NULL)
            free(value->element);
    }
}

int noeud_equals(const Noeud* value, const Noeud* operande)
{
    if((value == NULL) || (operande == NULL))
        return 0;
    else
    {
       /* return ( (list_equals(&value->successeurs, &operande->successeurs)) &&
                 (list_equals(&value->predecesseurs, &operande->predecesseurs)) &&
                 (strcmp(value->element, operande->element) == 0));*/
        return (strcmp(value->element, operande->element) == 0);
    }
}

void noeud_copy(const Noeud* value, Noeud* ret)
{
    if(ret != NULL)
        noeud_clear(ret);
    noeud_initialize(ret,value->element);
    list_copy(&(ret->successeurs),&(value->successeurs));
    list_copy(&(ret->predecesseurs),&(value->predecesseurs));
}

int noeud_addSuccessor(Noeud* noeud, Noeud* successor, int cost)
{
    Arc* arc;
    arc_create(&arc, noeud, successor, cost);
    if(list_contains(&noeud->successeurs,(void*)(arc)) ||
            list_contains(&successor->predecesseurs,(void*)(arc)))
        return 0;
    list_insertLast(&noeud->successeurs,(void*)(arc));
    list_insertLast(&successor->predecesseurs,(void*)(arc));
    return 1;
}

int noeud_removePredecessor(Noeud* noeud, Noeud* predecessor, int cost)
{
    int ret;
    Arc arc;
    Arc *suc, *pre;
    arc_initialize(&arc,predecessor,noeud,cost);
    suc = list_getValueAt(&predecessor->successeurs,list_getFirstOf(&predecessor->successeurs,(void*)(&arc),NULL));
    pre = list_getValueAt(&noeud->predecesseurs,list_getFirstOf(&noeud->predecesseurs,(void*)(&arc),NULL));
    ret = list_removeFirstOf(&predecessor->successeurs,(void*)(&arc));
    if(ret != -1)
        ret = (list_removeFirstOf(&noeud->predecesseurs,(void*)(&arc)) != -1);
    free(pre);
    return ret;
}

int noeud_removeSuccessor(Noeud* noeud, Noeud* successor, int cost)
{
    int ret;
    Arc arc;
    Arc *suc, *pre;
    arc_initialize(&arc,noeud,successor,cost);
    suc = list_getValueAt(&successor->predecesseurs,list_getFirstOf(&successor->predecesseurs,(void*)(&arc),NULL));
    pre = list_getValueAt(&noeud->successeurs,list_getFirstOf(&noeud->successeurs,(void*)(&arc),NULL));
    ret = list_removeFirstOf(&successor->predecesseurs,(void*)(&arc));
    if(ret != -1)
        ret = (list_removeFirstOf(&noeud->successeurs,(void*)(&arc)) != -1);
    free(suc);
    return ret;
}

Object* object_getNoeud()
{
    object_initialize(&_object_Noeud,
                      _noeud_toString,
                      _noeud_equals,
                      _noeud_copy,
                      _noeud_create,
                      _noeud_initialize,
                      _noeud_clear,
                      _noeud_destroy);
    return &_object_Noeud;
}

void _noeud_toString(const void* value, int fd)
{
    char buf[80];
    int size = sprintf(buf,"Noeud");
    write(fd,buf,size);
}

int _noeud_equals(const void* value, const void* operande)
{
    return noeud_equals((Noeud*)value,(Noeud*)operande);
}

int _noeud_copy(const void* value, void* ret)
{
    noeud_copy((Noeud*)value,(Noeud*)ret);
    return 1;
}

int _noeud_create(void** value, void* args)
{
    noeud_create((Noeud**)value, (char*) args);
    return 1;
}

int _noeud_initialize(void* value, void* args)
{
    noeud_initialize((Noeud*)value,(char*)args);
    return 1;
}

void _noeud_destroy(void** value)
{
    noeud_destroy((Noeud**)value);
}

void _noeud_clear(void* value)
{
    noeud_clear((Noeud*)value);
}
